/*
 * This file is Copyright 2002-2006 Loyola University Chicago,
 * Department of Computer Science and the Emerging Technologies Laboratory.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License via
 *    http://www.apache.org/licenses/LICENSE-2.0.
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.citep.formats.input.transactions;

import java.io.*;
import java.math.BigDecimal;

import com.citep.formats.input.ImportException;
import com.citep.formats.input.accounts.ImportedAccount;
import com.citep.formats.ofx.*;
import com.citep.business.*;



public class OFXImport extends TransactionImportStrategy implements OFXListener {


	private StatementImportSink handler;
	
	
	public OFXImport(DataInputStream stream) {
		super(stream);
	}
	
	public void setStatementHandler(StatementImportSink handler) {
		this.handler = handler;
	}

	public void start() throws ImportException {
		StringBuffer buf = new StringBuffer();

		BufferedReader ofx = new BufferedReader(new InputStreamReader(input));
		
		try {
			String line = null;
			while((line = ofx.readLine()) != null) {
				buf.append(line);
			}
		} catch(IOException e) {
			throw new ImportException("There was an error while reading the file: " + e.getMessage());
		}
		
		String text = buf.toString();
		System.out.println("text: " + text);
		OFXParser parser = new OFXParser(this);
		try {
			parser.feed(text);
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println(e.getStackTrace());
			throw new ImportException("Could not import ofx file: " + e.getMessage());
		}
	}

	public void onOFXStatement(OFXStatement ofxStatement) {
		
		System.out.println("statement ready: " + ofxStatement);
		ImportedStatement statement = new ImportedStatement();
		
		ImportedAccount destination = new ImportedAccount();
		OFXAccount bankAccount = ofxStatement.getFromAccount();
		if(bankAccount != null) {
			if(bankAccount.getAccountName() != null)
				destination.setName(bankAccount.getAccountId() + " " + bankAccount.getAccountName());
			else
				destination.setName(bankAccount.getAccountId());
			//destination.setId(Integer.parseInt(bankAccount.getAccountId()));
		}
		
		statement.setAccount(destination);
		
		//process all imported transactions
		
		int fakeId = 0; //use a temporary id to identify entries
		for(OFXTransaction t:ofxStatement.getTransactions()) {
			ImportedEntry e = new ImportedEntry();
			e.setAmount(t.getAmount());
			e.setMemo(t.getMemo());
			e.setAccount(destination);

			//FIXME: make sure these are actually debits or credits
			//usually bank statements have the oposite type of entries
			switch(t.getTransactionType()) {
				case DIV:
				case DEP:
				case CREDIT:
				case DIRECTDEP:
					e.setType(EntryTypes.CREDIT);
					e.setAmount(t.getAmount());
					break;

				case CHECK:
				case DEBIT:
				case DIRECTDEBIT:
				case FEE:
				case SRVCHG:
				case PAYMENT:
					e.setType(EntryTypes.DEBIT);
					e.setAmount(t.getAmount());
					break;
					
				case INT:
				case ATM:
					if(t.getAmount().floatValue() < 0) {
						//if the amount is negative this is a credit
						e.setType(EntryTypes.DEBIT);
						e.setAmount(t.getAmount().multiply(new BigDecimal(-1)));
					} else {
						e.setType(EntryTypes.CREDIT);
						e.setAmount(t.getAmount());
					}
					break;
					
				case XFER:
					e.setType(EntryTypes.DEBIT);
					e.setAmount(t.getAmount());
					break;
				case REPEATPMT:
					e.setType(EntryTypes.DEBIT);
					e.setAmount(t.getAmount());
					break;
				case OTHER:
					e.setType(EntryTypes.DEBIT);
					e.setAmount(t.getAmount());
					break;
			}
			
			e.setId(++fakeId);
			
			if(e.getMemo() != null)
				e.setMemo(t.getMemo());// + " (" + t.getTransactionType() + ")");
			else
				e.setMemo(t.getName());
			
			e.setDate(t.getDatePosted());
			
			statement.addEntry(e);
		}
		
		//alert the listener that a new statement is ready
		if(handler != null) {
			handler.onImportStatement(statement);
		}
	}

	public void onProcessingDone() {
		if(handler != null)
			handler.onDocumentEnd();
	}

}
